package expression;

import runtime.TypeFactory;
import util.Result;
import util.Scope;
import exception.ExpressionException;
import exception.TypeException;

/**
 * Klasa odpowiedzialna za przetrzymywanie wyrazenia negacji
 * 
 * @author Jakub Fibinger
 *
 */
public class NegationExpression extends Expression {
	/**
	 * Wyrazenie nizszego poziomu 
	 */
	private Expression expression;
	/**
	 * Znak informujacy o obecnosci lub braku znaku negacji
	 */
	private Sign sign;
	
	public static enum Sign {
		NOT,
		NONE;
	}

	/**
	 * @param scope Zakres zmiennych
	 * @param expression Wyrazenie nizszego poziomu
	 * @param sign Znak negacji lub jego brak
	 * @throws ExpressionException
	 */
	public NegationExpression(Scope scope, Expression expression, Sign sign) throws ExpressionException {
		if (expression == null) {
			throw new ExpressionException();
		}
		TypeFactory tf = TypeFactory.getInstance();
		try {
			if ( sign.equals(Sign.valueOf("NOT")) && !expression.getResultType().equals(tf.getType("bool")) ) {
				throw new ExpressionException();
			}
		} catch (TypeException e) {
			// zignoruj
		}
		this.expression = expression;
		this.sign = sign;
		this.result = new Result(expression.getResultType(), null);
	}

	/* (non-Javadoc)
	 * @see expression.Expression#evaluate()
	 */
	@Override
	public Result evaluate() throws ExpressionException {
		
		if(sign.equals(Sign.valueOf("NOT"))) {
			result.setValue(!(Boolean)(expression.evaluate().getValue()));
		} else {
			result.setValue(expression.evaluate().getValue());
		}
		
		return result;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	public String toString(){
		return "Negation [ sign: " + sign + ", " + expression + "]";
	}
}
